/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/

#include "beachday.h"

#define NO_LED_MODE_REQ     0xFFFFFFFF
uint32_t LEDModeRequest = NO_LED_MODE_REQ;

#define EMPTY_PATTERN      { 0, 0, 0 }
LED_PATTERN GlobalPattern = EMPTY_PATTERN;
LED_PATTERN CustomPattern[LED_COUNT] = { (LED_PATTERN)EMPTY_PATTERN };

uint32_t ServLED( void )
{
    static uint32_t st = LED_MODE_OFF, rnd = 12345, Stamp = 0;
    uint32_t i = 0;
    
    // mode-specific variables
    uint32_t a, b, c, adc;
    
    if(LEDModeRequest == NO_LED_MODE_REQ)
    {
        st = LED_MODE_OFF;
    }
    
    switch(st)
    {
        case LED_MODE_OFF:
            for(i = 0; i < LED_COUNT; i++)
            {
                SetWS2812B(i, WS2812B_CFG_OFF);
            }
            if((LEDModeRequest != NO_LED_MODE_REQ) && (!WS2812B_IS_BUSY))
            {
                st = LEDModeRequest;
            }
            break;
        case LED_MODE_STATE:
            a = GetState(IR);      // blue
            b = GetState(SYS);     // yellow
            c = GetState(LED);     // green
            for(i = 0; i < LED_COUNT; i++)
            {
                SetWS2812B(i, WS2812B_CFG_OFF);
                if(i < a + b + c)
                    SetWS2812B(i, WS2812B_CFG_GREEN);
                if(i < a + b)
                    SetWS2812B(i, WS2812B_CFG_YELLOW);
                if(i < a)
                    SetWS2812B(i, WS2812B_CFG_BLUE);
            }
            
            if(LEDModeRequest != LED_MODE_STATE)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_VALUE:
            if(GetState(SSD1306) == SSD1306_ST_IDLE)
            {
                if(GetTick() - Stamp >= (SSD1306_REFRESH_PERIOD >> 1))
                {
                    adc = GetFrameCount();
                    a = adc / 100;
                    b = (adc / 10) - (10 * a);
                    c = (adc) - (100 * a) - (10 * b);
                    for(i = 0; i < LED_COUNT; i++)
                    {
                        SetWS2812B(i, WS2812B_CFG_OFF);
                        if(i < a + b + c)
                            SetWS2812B(i, WS2812B_CFG_GREEN);
                        if(i < a + b)
                            SetWS2812B(i, WS2812B_CFG_YELLOW);
                        if(i < a)
                            SetWS2812B(i, WS2812B_CFG_BLUE);
                    }
                    Stamp = GetTick();
                }
            }
            
            if(LEDModeRequest != LED_MODE_VALUE)
            {
                st = LED_MODE_IDLE;
            }
            
            break;
        case LED_MODE_ADC_SENSOR:
            if(GetState(MQ303) == MQ303_ST_MAINT)
            {
                for(i = 0; i < LED_COUNT; i++)
                {
                    SetWS2812B(i, WS2812B_CFG_RED);
                }
            }
            else
            {
                adc = GetADC(ADC_CH_SENSOR);// GetMQ303();
                a = adc / 1000;
                b = (adc / 100) - (10 * a);
                c = (adc / 10) - (100 * a) - (10 * b);
                for(i = 0; i < LED_COUNT; i++)
                {
                    SetWS2812B(i, WS2812B_CFG_OFF);
                    if(i < a + b + c)
                        SetWS2812B(i, WS2812B_CFG_GREEN);
                    if(i < a + b)
                        SetWS2812B(i, WS2812B_CFG_YELLOW);
                    if(i < a)
                        SetWS2812B(i, WS2812B_CFG_BLUE);
                }
            }
            
            if(LEDModeRequest != LED_MODE_ADC_SENSOR)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_ADC_ANIMATION:
            adc = GetTick() - Stamp;
            for(i = 0; i < WS2812B_LED_COUNT; i++)
            {
                SetWS2812B(i, WS2812B_CFG_OFF);
            }
            switch(adc / 500)
            {
                case 0:
                    for(i = 0; i < (8 * (adc % 500)) / 500; i++)
                    {
                        SetWS2812B(i, WS2812B_CFG_RED);
                    }
                    break;
                case 1:
                    for(i = 0; i < 8; i++)
                    {
                        SetWS2812B(i, WS2812B_CFG_MAGENTA);
                    }
                    SetWS2812B(8, WS2812B_CFG_WHITE);
                    SetWS2812B(9, WS2812B_CFG_WHITE);
                    SetWS2812B(10, WS2812B_CFG_WHITE);
                    SetWS2812B(11, WS2812B_CFG_WHITE);
                    SetWS2812B(12, WS2812B_CFG_WHITE);
                    SetWS2812B(13, WS2812B_CFG_WHITE);
                    SetWS2812B(14, WS2812B_CFG_WHITE);
                    SetWS2812B(15, WS2812B_CFG_WHITE);
                    SetWS2812B(16, WS2812B_CFG_WHITE);
                    break;
                case 2:
                    for(i = 0; i < 8; i++)
                    {
                        SetWS2812B(i, WS2812B_CFG_OFF);
                    }
                    SetWS2812B(8, WS2812B_CFG_BLUE);
                    SetWS2812B(9, WS2812B_CFG_BLUE);
                    SetWS2812B(10, WS2812B_CFG_BLUE);
                    SetWS2812B(11, WS2812B_CFG_BLUE);
                    SetWS2812B(12, WS2812B_CFG_BLUE);
                    SetWS2812B(13, WS2812B_CFG_BLUE);
                    SetWS2812B(14, WS2812B_CFG_BLUE);
                    SetWS2812B(15, WS2812B_CFG_BLUE);
                    SetWS2812B(16, WS2812B_CFG_BLUE);
                    break;
                case 3:
                    SetWS2812B(8, WS2812B_CFG_GREEN);
                    SetWS2812B(9, WS2812B_CFG_GREEN);
                    SetWS2812B(10, WS2812B_CFG_GREEN);
                    SetWS2812B(11, WS2812B_CFG_GREEN);
                    SetWS2812B(12, WS2812B_CFG_GREEN);
                    SetWS2812B(13, WS2812B_CFG_GREEN);
                    SetWS2812B(14, WS2812B_CFG_GREEN);
                    SetWS2812B(15, WS2812B_CFG_GREEN);
                    SetWS2812B(16, WS2812B_CFG_GREEN);
                    break;
            }
            
            if(GetTick() - Stamp > (rnd % 500) + 1250)
            {
                Stamp = GetTick();
                a=rnd>>8;
                b=rnd&0xFF;
                a=a*18273+b;
                b=b*29379+a;
                rnd=((a&0xFF)<<8)|(b&0xFF);
            }
            
            if(LEDModeRequest != LED_MODE_ADC_ANIMATION)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_ADC_BATTERY:
            adc = GetADC(ADC_CH_BATTERY);
            a = adc / 1000;
            b = (adc / 100) - (10 * a);
            c = (adc / 10) - (100 * a) - (10 * b);
            for(i = 0; i < LED_COUNT; i++)
            {
                SetWS2812B(i, WS2812B_CFG_OFF);
                if(i < a + b + c)
                    SetWS2812B(i, WS2812B_CFG_GREEN);
                if(i < a + b)
                    SetWS2812B(i, WS2812B_CFG_YELLOW);
                if(i < a)
                    SetWS2812B(i, WS2812B_CFG_BLUE);
            }
            
            if(LEDModeRequest != LED_MODE_ADC_BATTERY)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_CODE_COUNT:
            adc = GetIRCode();
            a = adc / 100;
            b = (adc / 10) - (10 * a);
            c = (adc) - (100 * a) - (10 * b);
            for(i = 0; i < LED_COUNT; i++)
            {
                SetWS2812B(i, WS2812B_CFG_OFF);
                if(i < a + b + c)
                    SetWS2812B(i, WS2812B_CFG_GREEN);
                if(i < a + b)
                    SetWS2812B(i, WS2812B_CFG_YELLOW);
                if(i < a)
                    SetWS2812B(i, WS2812B_CFG_BLUE);
            }
            
            if(LEDModeRequest != LED_MODE_CODE_COUNT)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_INPUT_DISPLAY:
            for(i = 0; i < LED_COUNT; i++)
            {
                SetWS2812B(i, ((GetState(CS)) ? WS2812B_CFG_RED : WS2812B_CFG_BLUE));
                if(GetCSProxState()) SetWS2812B(i, WS2812B_CFG_YELLOW);
            }
            
            if(Enter_Read() == GPIO_LOW) SetWS2812B(0, WS2812B_CFG_OFF);
            if(Right_Read() == GPIO_LOW) SetWS2812B(1, WS2812B_CFG_OFF);
            if(Left_Read() == GPIO_LOW) SetWS2812B(2, WS2812B_CFG_OFF);
            if(Up_Read() == GPIO_LOW) SetWS2812B(3, WS2812B_CFG_OFF);
            if(Down_Read() == GPIO_LOW) SetWS2812B(4, WS2812B_CFG_OFF);
            
            if(LEDModeRequest != LED_MODE_INPUT_DISPLAY)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_GLOBAL:
            for(i = 0; i < LED_COUNT; i++)
            {
                if((GetTick() % GlobalPattern.period) >= (GlobalPattern.period * GlobalPattern.duty) / 100)
                {
                    SetWS2812B(i, WS2812B_CFG_OFF);
                }
                else
                {
                    SetWS2812B(i, ((WS2812B_CONFIG*)GlobalPattern.cfg)->id);
                }
            }
            
            if(LEDModeRequest != LED_MODE_GLOBAL)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_CUSTOM:
            for(i = 0; i < LED_COUNT; i++)
            {
                if((GetTick() % CustomPattern[i].period) >= (CustomPattern[i].period * CustomPattern[i].duty) / 100)
                {
                    SetWS2812B(i, WS2812B_CFG_OFF);
                }
                else
                {
                    SetWS2812B(i, ((WS2812B_CONFIG*)CustomPattern[i].cfg)->id);
                }
            }
            
            if(LEDModeRequest != LED_MODE_CUSTOM)
            {
                st = LED_MODE_IDLE;
            }
            break;
        case LED_MODE_IDLE:
        default:
            
            LEDModeRequest = NO_LED_MODE_REQ;
            st = LED_MODE_OFF;
            break;
    }
    
    return st;
}

void SetGlobalLED( LED_PATTERN pat )
{
    GlobalPattern = pat;
}

void SetCustomLED( LED_PATTERN pat, uint32_t id )
{
    if(id < LED_COUNT)
    {
        CustomPattern[id] = pat;
    }
}

void RequestLEDMode( uint32_t mode)
{
    if(mode < LED_MODE_COUNT)
    {
        LEDModeRequest = mode;
    }
}


/* [] END OF FILE */
